package com.atxiaodei.javajuc.jucdemo;


import org.junit.jupiter.api.Test;

/*
 * 一、volatile 关键字：当多个线程进行操作共享数据时，可以保证内存中的数据可见。
 * 					  相较于 synchronized 是一种较为轻量级的同步策略。
 *
 * 注意：
 * 1. volatile 不具备“互斥性”
 * 2. volatile 不能保证变量的“原子性”
 *
 * 原子性是什么意思呢，回顾下我们上学的时候，学过原子，理解起来就是不可分割
 *
 *
 */
public class JucTestVolatile关键字原子性 {

    @Test
    public void test1(){
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();

        /*while(true){
            if(td.isFlag()){
                System.out.println("------------------");
                break;
            }
        }*/
        /**
         * 总结：
         *      该方法test1 方法体实质上有两个线程体  1是17-18行代码   2是20-25行代码
         *      执行结果呢，只打印了flag=true，为什么呢？
         *      因为线程1和线程2是同时运行的，而线程1故意睡了0.2秒  flag在还没有变成true的时候，线程2已经运行了，获取的flag是false
         *      所以线程2的输出语句没有执行，也就导致了线程2成了死循环
         *
         *      为了让这种情况不发生，我们可以选择两种方案：
         *                                      1、加上同步 synchronized 也就是用42-49行代码替换20-25行代码（jdk8之前的用法）
         *                                      2、使用关键字 volatile 修饰flag（jdk8的用法）
         *                                                          当多个线程进行操作共享数据时，可以保证内存中的数据可见。
         *
         *
         *
         *
         */
      /*  System.out.println("------------------------加上同步synchronized---------------------------");
        while(true) {
            synchronized (td) {
                if (td.isFlag()) {
                    System.out.println("------------------");
                    break;
                }
            }
        }*/

        System.out.println("------------------------volatile修饰flag属性 ---------------------------");

        while(true) {
                if (td.isFlag()) {
                    System.out.println("------------------");
                    System.out.println("当多个线程进行操作共享数据时，可以保证内存中的数据可见");
                    break;
                }
        }



    }

}
